
#ifndef _TTG_EXTRAS_SUBOPERATIONS_
#define _TTG_EXTRAS_SUBOPERATIONS_
#include "Common/Definitions.h"

#include "Operations.h"

namespace ttg_internal
{
	//Implements unary minus.
	template <class T>
	class UnaryMinusOperation :public ttg::extras::Operation<T>
	{
		protected:
			ttg::extras::Operation<T> *source;
		public:
			inline UnaryMinusOperation(ttg::extras::Operation<T> *source = NULL)
			{
				this->source = source;
			}
			//Operation member.
			virtual T calculate()
			{
				return -source->calculate();
			}
			//Operation member.
			virtual bool isStatic()
					{ return source->isStatic(); }
			~UnaryMinusOperation()
			{
				SAFE_DELETE(source);
			}
			//Creates operation with given sources. In case of error returns NULL.
			virtual OperationInfo *createInstance(OperationInfo *s1,
												  OperationInfo *s2,
												  OperationInfo *s3)
			{
				ttg::extras::Operation<T> *op = dynamic_cast<ttg::extras::Operation<T> *>(s1);
				if (op == NULL)
					return NULL;
				else
					return new UnaryMinusOperation<T>(op);
			}
	};

	//Implements simple substraction of one-type values.
	template <class T>
	class SubOperation :public ttg::extras::Operation<T>
	{
		protected:
			ttg::extras::Operation<T> *source1;
			ttg::extras::Operation<T> *source2;
		public:
			inline SubOperation(ttg::extras::Operation<T> *source1 = NULL,
								ttg::extras::Operation<T> *source2 = NULL)
			{
				this->source1 = source1;
				this->source2 = source2;
			}
			//Operation member.
			virtual T calculate()
			{
				return source1->calculate() - source2->calculate();
			}
			//Operation member.
			virtual bool isStatic()
					{ return source1->isStatic() && source2->isStatic(); }
			~SubOperation()
			{
				SAFE_DELETE(source1);
				SAFE_DELETE(source2);
			}
			//Creates operation with given sources. In case of error returns NULL.
			virtual OperationInfo *createInstance(OperationInfo *s1,
												  OperationInfo *s2,
												  OperationInfo *s3)
			{
				ttg::extras::Operation<T> *op1 = dynamic_cast<ttg::extras::Operation<T> *>(s1);
				ttg::extras::Operation<T> *op2 = dynamic_cast<ttg::extras::Operation<T> *>(s2);
				if (op1 == NULL || op2 == NULL)
					return NULL;
				else
					return new SubOperation<T>(op1, op2);
			}
	};
}

#endif
